package com.smartahc.android.camera

import android.graphics.*
import android.os.Bundle
import android.os.Looper
import android.os.MessageQueue
import android.support.v7.app.AppCompatActivity
import android.util.Log
import com.smartahc.android.camera.MTCNN.Box
import com.smartahc.android.camera.MTCNN.MTCNN
import com.smartahc.android.camera.ternsorflow.Classifier
import com.smartahc.android.camera.ternsorflow.TensorFlowImageClassifier
import kotlinx.android.synthetic.main.activity_camera.*
import kotlinx.android.synthetic.main.activity_image_analysis.*
import org.opencv.android.CameraBridgeViewBase
import org.opencv.android.Utils
import org.opencv.core.*
import org.opencv.core.Point
import org.opencv.imgproc.Imgproc
import org.opencv.imgproc.Imgproc.*
import java.io.IOException
import java.util.*
import java.util.concurrent.Executor
import java.util.concurrent.ScheduledThreadPoolExecutor
import java.util.concurrent.ThreadFactory

class CameraActivity : AppCompatActivity(), CameraBridgeViewBase.CvCameraViewListener2 {

    private var mRgba = Mat()

    private val INPUT_SIZE = 64 //图片输入尺寸
    private val IMAGE_MEAN = 127
    private val IMAGE_STD = 127f
    private val INPUT_NAME = "模型输入节点名称"
    private val OUTPUT_NAME = "模型输出节点名称"
    private val MODEL_FILE = "file:///android_asset/model/tensorflow模型.pb"
    private val LABEL_FILE = "file:///android_asset/model/标签.txt"

    private var executor: Executor? = null
    private var classifier: Classifier? = null

    private lateinit var facd: MTCNN


   private var emores = "no emotiom"

    private var left_point = 0
    private var top_point = 0
    private var right_point = 0
    private var bottom_point = 0

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_camera)

        cameraView.setCameraIndex(0) // 0:后置 1:前置
//        cameraView.enableFpsMeter() //显示FPS
        cameraView.setCvCameraViewListener(this)
        cameraView.enableView()

        // 避免耗时任务占用 CPU 时间片造成UI绘制卡顿，提升启动页面加载速度
        Looper.myQueue().addIdleHandler(idleHandler)
    }

    /**
     * 主线程消息队列空闲时（视图第一帧绘制完成时）处理耗时事件
     */
    private var idleHandler: MessageQueue.IdleHandler = MessageQueue.IdleHandler {
        if (classifier == null) {
            // 创建 Classifier
            classifier = TensorFlowImageClassifier.create(this@CameraActivity.assets,
                    MODEL_FILE, LABEL_FILE, INPUT_SIZE, IMAGE_MEAN, IMAGE_STD, INPUT_NAME, OUTPUT_NAME)
        }

        //加载检测权重
        facd = MTCNN(this@CameraActivity.assets)


        // 初始化线程池
        executor = ScheduledThreadPoolExecutor(1, ThreadFactory { r ->
            val thread = Thread(r)
            thread.isDaemon = true
            thread.name = "ThreadPool-ImageClassifier"
            thread
        })

        false
    }


    override fun onCameraViewStarted(width: Int, height: Int) {
        mRgba = Mat(height, width, CvType.CV_8UC4)
    }

    override fun onCameraViewStopped() {
        mRgba.release()
    }


    /*
    * ##################################################################################################################################################################################
    * */

    //裁切图片:依据矩形框裁切图片
    fun clipBitmap(bitmap: Bitmap, left: Int, top: Int, right: Int, bottom: Int): Bitmap{
        var left = left
        var top = top
        var right = right
        var bottom = bottom
        return Bitmap.createBitmap(bitmap, left, top, right - left, bottom - top)
    }


    override fun onCameraFrame(inputFrame: CameraBridgeViewBase.CvCameraViewFrame): Mat {
        mRgba = inputFrame.rgba()

        val bmpCanny = Bitmap.createBitmap(mRgba.cols(), mRgba.rows(), Bitmap.Config.ARGB_8888)
        Utils.matToBitmap(mRgba, bmpCanny)

        //人脸检测
        var box: Vector<Box> = facd.detectFaces(bmpCanny, 16)

        //box坐标防溢出
        if(box.get(0).right() >box.get(0).left() && box.get(0).bottom() > box.get(0).top() ){
            if(box.get(0).left()<0){
                left_point = 0
            }else{
                left_point = box.get(0).left()
            }
            if(box.get(0).top()<0){
                top_point = 0
            }else{
                top_point = box.get(0).top()
            }
            right_point = box.get(0).right()
            bottom_point = box.get(0).bottom()

        executor?.execute {
                //emotion classfier
                val croppedBitmap = getScaleBitmap(clipBitmap(bmpCanny, left_point, top_point, right_point, bottom_point), INPUT_SIZE)
                val results = classifier?.recognizeImage(croppedBitmap)
                emores = results.toString()
            }


        }
        bmpCanny.recycle() // release bitmap

        putText(mRgba, emores, Point(0.0, 30.0), Core.FONT_HERSHEY_COMPLEX, 1.0, Scalar(255.0))
        rectangle(mRgba, Point(left_point.toDouble(), top_point.toDouble()), Point(right_point.toDouble(), bottom_point.toDouble()), Scalar(0.0, 255.0, 0.0, 0.0), 3)

        return mRgba
    }
    /*
    * ##################################################################################################################################################################################
    * */

    /**
     * 对图片进行缩放
     * @param bitmap
     * @param size
     * @return
     * @throws IOException
     */
    @Throws(IOException::class)
    private fun getScaleBitmap(bitmap: Bitmap, size: Int): Bitmap {
        val width = bitmap.width
        val height = bitmap.height
        val scaleWidth = size.toFloat() / width
        val scaleHeight = size.toFloat() / height
        val matrix = Matrix()
        matrix.postScale(scaleWidth, scaleHeight)
        return Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true)
    }
}
